package yxy.cherry.paycenter.servlet.channel.weixin;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dom4j.DocumentException;

import com.alibaba.fastjson.JSONObject;

import yxy.apple.logger.Logger;
import yxy.cherry.game.base.bean.SDKParm;
import yxy.cherry.game.base.bean.SdkParmEnum;
import yxy.cherry.paycenter.channelmodule.weixin.PayMoudle_weixin;
import yxy.cherry.paycenter.database.dao.ordersDao;
import yxy.cherry.paycenter.database.db.orders;
import yxy.cherry.paycenter.servlet.channel.Servlet;
import yxy.cherry.paycenter.servlet.channel.jh.Servlet_jh;
import yxy.cherry.paycenter.util.HttpHelper;
import yxy.cherry.paycenter.util.HttpUtil;
import yxy.cherry.paycenter.util.wxUtil;
import yxy.game.pm2.bean.channel.SdkChannel;
import yxy.game.pm2.bean.module.OrderInfoModule;
import yxy.game.pm2.bean.sdk.WeiXinOtherParm;

/**
 * 微信 - ios - 公众号创建订单
 * @author Dell
 *
 */
public class Servlet_WeiXinPrePayIos extends Servlet{

	private static final int success = 1;		//成功
	private static final int dataerror = 2;		//数据错误，申请订单信息验签失败
	private static final int outtime = 3;		//超时
	private static final int orderfinsih = 4;	//订单已完成
	private static final int prepayerror = 5;	//weixin 预订单失败
	
	private static String wx_return_success = "SUCCESS"; 	//微信预订单返回码 成功

	private static String jh_order_checklogin = "https://pay.api.xjhgame.net/union/miniapp/order/submit";
	private static String jh_order_success = "200";
	
	private static String wx_order = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	
	//支付相关
	private static int NoChannel = 6200;	//渠道不存在
	private static int NoGoods = 6201;		//商品不存在
	private static int HadGetGoods = 6202;	//商品限购，不能购买
	private static int PayFail = 6203;		//购买失败
	private static int PaySucess = 6206;	//购买成功
	
	private static final Logger logger = Logger.create(Servlet_jh.class);

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	}

	@Override
	public String getUrl() {
		return "/sdk_" + getChannel() + "pre" + PayMoudle_weixin.ios;
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		HttpUtil.printlnParseMap("Servlet_WeiXinPrePayIo_post", req);
		JSONObject rjson = new JSONObject();

		JSONObject json = HttpUtil.getParseJSON(req);
		logger.info("Servlet_WeiXinPrePayIos json " + json);

		String ip = req.getLocalAddr();
//		logger.info("Servlet_WeiXinPrePayIos ip:" + ip);
		
		//接受参数示例
		
		int uid = json.getIntValue("uid");
		String sign = json.getString("sign");
		String myorderid = json.getString("out_trade_no");

		JSONObject signjson = new JSONObject();
		signjson.put("uid", uid);
		signjson.put("channel", json.getString("channel"));
		signjson.put("sid", json.getIntValue("sid"));
		signjson.put("out_trade_no", myorderid);
		signjson.put("fee_type", json.getString("fee_type"));
		signjson.put("total_fee", json.getString("total_fee"));
		signjson.put("product_id", json.getString("product_id"));
		signjson.put("time", json.getLongValue("time"));
		signjson.put("code", json.getString("code"));
		
		String signjsonstr = HttpUtil.getSignData(signjson, null, null);
		signjsonstr = signjsonstr + "&key=" + SDKParm.getSdkparmvalue(SdkParmEnum.weixin_yuwan_apisecretkey);
		String newsign = HttpUtil.getMD5(signjsonstr);
		if(!newsign.equals(sign)) {
			logger.info("Servlet_WeiXinPrePayIos oldsign:" + sign);
			logger.info("Servlet_WeiXinPrePayIos newsign:" + newsign);
			//数据错误
			rjson.put("result", dataerror);
			writeResponse(resp, rjson.toString());
			return;
		}

		WeiXinOtherParm wxop = WeiXinOtherParm.get(uid);
		String openid = wxop.getOpenid();
		String adId = wxop.getAdid() == null ? "" : wxop.getAdid();
				
		long time = json.getLongValue("time");
		long timenow = System.currentTimeMillis();
		if(timenow - time > 15*60000) {
			System.out.println("oldtime:" + time);
			System.out.println("newtime:" + timenow);
			//订单失败 超时
			rjson.put("result", outtime);
			writeResponse(resp, rjson.toString());
			return;
		}
		
		orders o = ordersDao.getOrderByMyorderid(myorderid);
		if(o != null) {
			if(o.getOrderstate() == OrderInfoModule.orderinfofinish) {
				//订单已完成
				rjson.put("result", orderfinsih);
				writeResponse(resp, rjson.toString());
				return;
			}else {
				//未完成 返回订单信息 TODO:
				String ext = o.getExt();
				if(ext != null && !ext.equals("")) {
//					rjson = JSON.parseObject(ext);
//					rjson.put("result", success);
					writeResponse(resp, ext);
					return;					
				}
			}
		}
			
		//统一下单
		String appid = SDKParm.getSdkparmvalue(SdkParmEnum.weixin_xcx_appid);	//微信支付分配的公众账号ID（企业号corpid即为此appId）
//		String appid = "wx37117d1989fe9efb";	//微信支付分配的公众账号ID（企业号corpid即为此appId）
		String mch_id = SDKParm.getSdkparmvalue(SdkParmEnum.weixin_mch_id);			//微信支付分配的商户号
		String nonce_str = wxUtil.generateNonceStr();	//随机字符串，长度要求在32位以内。
		String sign_type = "MD5";				//签名类型，默认为MD5，支持HMAC-SHA256和MD5。
		String body = o.getGoodsname();			//商品简单描述，该字段请按照规范传递，具体请见参数规定
		String out_trade_no = myorderid;		//商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|* 且在同一个商户号下唯一。详见商户订单号
		String fee_type = "CNY";				//符合ISO 4217标准的三位字母代码，默认人民币：CNY，详细列表请参见货币类型
		int total_fee = o.getGoodsprice();		
//			//TODO:-----------------------   一分测试用
//			total_fee = 1;
		
		String spbill_create_ip = ip;			//支持IPV4和IPV6两种格式的IP地址。用户的客户端IP
		//String notify_url = SDKParm.getSdkparmvalue(SdkParmEnum.weixin_zhima_callbak);
//		String notify_url = "http://ydsg-pgu.xjhgame.net:20000/sdk_weixin2";
		String notify_url = "http://pm2-beta.xjhgame.net:20000/sdk_weixin2";		//异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
//		String notify_url = "http://test.ios.tjyouai.com:14100/wxiospay";		//异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
		String trade_type = "JSAPI";		//JSAPI -JSAPI支付NATIVE -Native支付APP -APP支付
		String product_id = String.valueOf(o.getGoodsid());	//
				//openid trade_type=JSAPI时（即JSAPI支付），此参数必传，此参数为微信用户在商户对应appid下的唯一标识

		JSONObject postjson = new JSONObject();
		postjson.put("appid", appid);
		postjson.put("mch_id", mch_id);
		postjson.put("nonce_str", nonce_str);
		postjson.put("sign_type", sign_type);
		postjson.put("body", body);
		postjson.put("out_trade_no", out_trade_no);
//		postjson.put("attach", "");
		postjson.put("fee_type", fee_type);
		postjson.put("total_fee", total_fee);
		postjson.put("spbill_create_ip", spbill_create_ip);
		postjson.put("notify_url", notify_url);
		postjson.put("trade_type", trade_type);
		postjson.put("product_id", product_id);
		postjson.put("openid", openid);
		
		String signstr = getSignData(postjson, null, null);
		signstr = signstr + "&key=" + SDKParm.getSdkparmvalue(SdkParmEnum.weixin_yuwan_apisecretkey);
//		"TNMiIN0hG2Zkn4QctxIJ9gEEZRL6s76o";
		
		String sign1 = wxUtil.getMD5(signstr).toUpperCase();
		postjson.put("sign", sign1);	
		System.out.println("wxios postjson:" + postjson);
		
		byte[] bs = null;
		try {
			HashMap<String, String> pmap = new HashMap<String, String>();
			for(String key : postjson.keySet()) {
				String value = postjson.getString(key);
				pmap.put(key, value);
			}
			
			String postxml = wxUtil.mapToXml(pmap, false);
			System.out.println("wxios:" + postxml);
			bs = HttpHelper.doPost2(new URL(wx_order), "text/xml", postxml.getBytes());
		} catch (IOException e) {	
			e.printStackTrace();
		}

		String bsstr = "";
		try {
			bsstr = new String(bs, "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.out.println("bsstr:" + bsstr);

		JSONObject info = new JSONObject();
        try {
			info = wxUtil.xml2Json(bsstr);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		System.out.println(info);
		
		String return_code = info.getString("return_code");
		String result_code = info.getString("result_code");
		
		if(!result_code.equals("SUCCESS") || !return_code.equals("SUCCESS")) {
			//数据错误
			rjson.put("result", prepayerror);
			writeResponse(resp, rjson.toString());
			return;
		}
		
		String prepay_id = info.getString("prepay_id");
		
        String appId = SDKParm.getSdkparmvalue(SdkParmEnum.weixin_xcx_appid);// "wx3226b21e8c402f0f";
		String timeStamp = String.valueOf(System.currentTimeMillis()/1000);
        String nonceStr = wxUtil.generateNonceStr();
		String packagestr = "prepay_id=" + prepay_id;
        String signType = "MD5";
		
        rjson.put("appId", appId);
        rjson.put("timeStamp", timeStamp);
        rjson.put("nonceStr", nonceStr);
        rjson.put("package", packagestr);
        rjson.put("signType", signType);
        
		String rjsonsignstr = getSignData(rjson, null, null);
		rjsonsignstr = rjsonsignstr + "&key=" + SDKParm.getSdkparmvalue(SdkParmEnum.weixin_yuwan_apisecretkey); //"TNMiIN0hG2Zkn4QctxIJ9gEEZRL6s76o";
		System.out.println("wxios rjsonsignstr:" + rjsonsignstr);
		String rjsonsign = wxUtil.getMD5(rjsonsignstr).toUpperCase();
		System.out.println("wxios rjsonsign:" + rjsonsign);
        
		rjson.put("paySign", rjsonsign);
		
		o.setExt(rjson.toString());
		ordersDao.update(o);
		
		rjson.put("result", success);
	

		
		o.setExt(rjson.toString());
		ordersDao.update(o);

		
		writeResponse(resp, rjson.toString());
	}

	public static void writeResponse(HttpServletResponse resp, String retstr) {
		String type = "application/x-www-form-urlencoded";
		writeResponse(resp, type, retstr);
	}

	public static void writeResponse(HttpServletResponse resp, String type, String retstr) {
		resp.setHeader("Access-Control-Allow-Origin", "*");
		resp.setHeader("Access-Control-Allow-Credentials", "true");
		resp.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
		resp.setHeader("Access-Control-Allow-Headers",
				"Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With");
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType(type);
		resp.setStatus(HttpServletResponse.SC_OK);

		PrintWriter pw = null;
		try {
			pw = resp.getWriter();
			pw.write(retstr);
		} catch (Exception e) { 
			e.printStackTrace();
		} finally {
			if (pw != null) {
				pw.flush();
				pw.close();
			}
		}
	}

	public static String getSignData(JSONObject parseobj, String scretkey, String secret) {
		// params为要参与签名的参数键值对.
		StringBuffer content = new StringBuffer();
		// 按照key做排序

		Set<String> parseset = parseobj.keySet();
		List<String> list = sortSet(parseset);

		for (int i = 0; i < list.size(); i++) {
			String key = list.get(i);
			if ("sign".equals(key))
				continue;

			String value = parseobj.getString(key);
			if (value != null) {
				content.append((i == 0 ? "" : "&") + key + "=" + value);
			}
		}

		if (scretkey != null) {
			content.append("&").append(scretkey).append("=");			
		}

		if(secret != null) {
			content.append(secret);			
		}

		return content.toString();
	}
	
	public static List<String> sortSet(Set<String> set) {
		List<String> strlist2 = new ArrayList<>();
		strlist2.addAll(set);
		Collections.sort(strlist2);

		return strlist2;
	}
	
	@Override
	public String getChannel() {
		return SdkChannel.sdk_weixin;
	}

}
